package org.robcash.flexlib.controls
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import mx.containers.Box;
	import mx.containers.HBox;
	import mx.controls.Label;
	import mx.controls.NumericStepper;
	import mx.core.mx_internal;
	import mx.events.FlexEvent;

	public class MinutesAndSecondsStepper extends HBox
	{
		private var _minutesValue:int = 1;
		private var _minutesIncrement:int = 1;
		private var _minutesMaximum:int = 59;
		private var _secondsValue:int = 0;
		private var _secondsIncrement:int = 1;

		private var minutes:NumericStepper;
		private var seconds:NumericStepper;
		private var colon:Label;
		private var lastSecondsValue:int = 0;
		private var enabledChanged:Boolean = false;

		public function MinutesAndSecondsStepper()
		{
			super();
			super.setStyle("horizontalGap", 0);
		}
		
		// ---------------------------------------------------------
		// Accessor Methods
		// ---------------------------------------------------------

		[Bindable]
		[Inspectable(defaultValue = "1", category="General")]
		public function get minutesValue():int
		{
			if ( minutes )
			{
				return minutes.value;
			}
			else
			{
				return _minutesValue;
			}
		} 
		
		public function set minutesValue(value:int):void
		{
			_minutesValue = value;
			if ( minutes )
			{
				minutes.value = value;
			}
		}
		
		[Bindable]
		[Inspectable(defaultValue = "0", category="General")]
		public function get secondsValue():int
		{
			if ( seconds )
			{
				return seconds.value;
			}
			else
			{
				return _secondsValue;
			}
		} 
		
		public function set secondsValue(value:int):void
		{
			_secondsValue = value;
			if ( seconds )
			{
				seconds.value = value;
			}
		}
		
		[Bindable]
		[Inspectable(defaultValue = "1", category="Other")]
		public function get minutesIncrement():int
		{
			if ( minutes )
			{
				return minutes.stepSize;
			}
			else
			{
				return _minutesIncrement;
			}
		} 
		
		public function set minutesIncrement(increment:int):void
		{
			_minutesIncrement = increment;
			if ( minutes )
			{
				minutes.stepSize = increment;
			}
		}
		
		[Bindable]
		[Inspectable(defaultValue = "1", category="Other")]
		public function get secondsIncrement():int
		{
			if ( seconds )
			{
				return seconds.stepSize;
			}
			else
			{
				return _secondsIncrement;
			}
		}

		public function set secondsIncrement(increment:int):void
		{
			_secondsIncrement = increment;
			if ( seconds )
			{
				seconds.stepSize = increment;
			}
		}
		
		[Bindable]
		[Inspectable(defaultValue = "59", category="Other")]
		public function get maximumMinutes():int
		{
			if ( minutes )
			{
				return minutes.maximum;
			}
			else
			{
				return _minutesMaximum;
			}
		}

		public function set maximumMinutes(maximum:int):void
		{
			_minutesMaximum = maximum;
			if ( minutes )
			{
				minutes.maximum = maximum;
			}
		}

		// ---------------------------------------------------------
		// Public Methods
		// ---------------------------------------------------------
		
		public function getTimeInSeconds():int
		{
			return minutes.value * 60 + seconds.value;
		}
		
		// ---------------------------------------------------------
		// Override Methods
		// ---------------------------------------------------------
		
		[Bindable]
		public override function get enabled():Boolean
		{
			return super.enabled;
		}
		
		public override function set enabled(value:Boolean):void
		{
			super.enabled = value;
			enabledChanged = true;
		}
		
		protected override function createChildren():void
		{
			super.createChildren();
			
			if ( !minutes )
			{
				minutes = new NumericStepper();
				minutes.minimum = 0;
				minutes.maximum = _minutesMaximum;
				minutes.stepSize = _minutesIncrement;
				minutes.value = _minutesValue;
				minutes.setStyle("textAlign", "right");
				addChild(minutes);
				
				// There's nothing that this component needs to do when
				// the minutes value changes, but calling handleChange
				// will enable users of this component to be notified
				minutes.addEventListener("change", handleChange);
			}
			
			if ( !colon )
			{
				colon = new Label();
				colon.text = ":";
				super.addChild(colon);
			}
			
			if ( !seconds )
			{
				seconds = new NumericStepper();
				seconds.minimum = 0;
				seconds.maximum = 59;
				seconds.stepSize = _secondsIncrement;
				seconds.addEventListener(Event.CHANGE, handleChange);
				seconds.addEventListener(FlexEvent.CREATION_COMPLETE, childComponentsCreated);
				// Set the value after adding the listener so that it can be formatted
				seconds.value = _secondsValue;
				super.addChild(seconds);
			}
		}
		
		protected override function commitProperties():void
		{
			super.commitProperties();

			if ( enabledChanged )
			{
				enabledChanged = false;
				minutes.enabled = enabled;
				seconds.enabled = enabled;
			}
		}
		
		// ---------------------------------------------------------
		// Event Handlers
		// ---------------------------------------------------------
		
		private function childComponentsCreated(event:Event):void
		{
			if ( event.currentTarget == seconds )
			{
				// Correct text field
				if ( seconds.value < 10 )
				{
					seconds.mx_internal::inputField.text = "0" + seconds.value;
				}
				
				// Add next/previous button listeners
				seconds.mx_internal::nextButton.addEventListener(MouseEvent.CLICK, handleValueIncrement);
				seconds.mx_internal::prevButton.addEventListener(MouseEvent.CLICK, handleValueDecrement);
			}
		} 
		
		private function handleChange(event:Event):void
		{
            if ( event.currentTarget == seconds )
            {
            	if ( seconds.value < 10 )
            	{
           			seconds.mx_internal::inputField.text = "0" + seconds.value;
           		}
            }

			// Dispatch event so change listeners (of this component) will be
			// notified 
            dispatchEvent(new Event("change"));
		}
		
		private function handleValueIncrement(event:Event):void
		{
			if ( event.currentTarget == seconds.mx_internal::nextButton )
			{
				// Check to see if value is at maximum and user is attempting
				// to increment anyway. This means resetting the value to the
				// minimum and incrementing the minutes value.
				if ( seconds.value == seconds.maximum &&
						seconds.value == lastSecondsValue )
				{
					// Value is at max and did not increment
					seconds.value = seconds.minimum;
					minutes.value++;
				}
				else
				{
					lastSecondsValue = seconds.value;
				}
			}
		}
		
		private function handleValueDecrement(event:MouseEvent):void
		{
			if ( event.currentTarget == seconds.mx_internal::prevButton )
			{
				// Check to see if value is at minimum and user is attempting
				// to decrement anyway. This means resetting the value to the
				// maximum and decrementing minutes value.
				if ( seconds.value == seconds.minimum &&
						seconds.value == lastSecondsValue )
				{
					// Value is at min and did not decrement
					seconds.value = seconds.maximum;
//					if ( minutes.value > 0 )
//					{
//						minutes.value--;
//					}
				}
				else
				{
					lastSecondsValue = seconds.value;
				}
			}
		}
	}
}